import koaRouter from 'koa-router'
import { resolve } from 'path'
import { readdirSync } from 'fs'
const r = path => resolve(__dirname, path)
const isArray = v => v instanceof Array ? v : [v]
const normalizePath = path => path.startsWith('/') ? path : `/${path}`
const symbolPrefix = Symbol('prefix')
let routerMap = new Map()

class Router {
  constructor(app, apiPath) {
    this.app = app
    this.apiPath = apiPath
    this.router = new koaRouter()
  }
  init() {
    readdirSync(this.apiPath)
      .filter(file => ~file.search(/^[^\.].*\.js$/))
      .forEach(file => require(resolve(this.apiPath, file)))
    for(let [conf, fn] of routerMap) {
      const fns = isArray(fn)
      let prefixPath = conf.target[symbolPrefix]
      if (prefixPath) prefixPath = normalizePath(prefixPath)
      const routerPath = prefixPath + conf.path
      this.router[conf.method](routerPath, ...fns)
    }
    
    this.app.use(this.router.routes())
    this.app.use(this.router.allowedMethods())
  }
}
const router = conf => (target, key, descriptor) => {
  conf.path = normalizePath(conf.path)
  routerMap.set({
    target: target,
    ...conf
  }, target[key])
}
export const controller = path => target => target.prototype[symbolPrefix] = path

export const get = path => router({
  method: 'get',
  path
}) 

export const post = path => router({
  method: 'post',
  path
})

export const convert = middleware => (target, key, descriptor) => {
  target[key] = isArray(target[key])
  target[key].unshift(middleware)
}



export const required = rules => convert(async (ctx, next) => {
  let errors = []
  const passRules = R.forEachObjIndexed((value, key) => {
    errors = R.filter(i => !R.has(i, ctx.request[key]))(value)
  })
  passRules(rules)

  if(errors.length) ctx.throw(412, `${errors.join(', ')}参数缺失`)

  await next()
})

export const route = app => {
  let apiPath = resolve(__dirname, '../api')
  const router = new Router(app, apiPath)
  router.init()
}

